#include "DoOpCoordinateMatrix.h"
#include "DevilSemantic.h"
#include "MatrixUtils.h"

void DoOpCoordinateMatrix::ds_matrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	state.getOpStack().push(MatrixUtils::identity());
}

void DoOpCoordinateMatrix::ds_initmatrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

void DoOpCoordinateMatrix::ds_identmatrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

void DoOpCoordinateMatrix::ds_defaultmatrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

void DoOpCoordinateMatrix::ds_currentmatrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

void DoOpCoordinateMatrix::ds_setmatrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

void DoOpCoordinateMatrix::ds_translate::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;

	if (obj1->type() == eArray) {
		obj3 = state.getOpStack().pop();
		float matrix[6];
		MatrixUtils::toMatrix(toArray(obj1), matrix);
		matrix[4] = toNumber(obj3)->getReal();
		matrix[5] = toNumber(obj2)->getReal();
		state.getOpStack().push(MatrixUtils::toArray(matrix));
	} else {
		CXXTHROW;
	}
}

void DoOpCoordinateMatrix::ds_scale::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	if (obj1->type() == eArray) {
		obj3 = state.getOpStack().pop(); 
		float x = toNumber(obj3)->getReal();
		float y = toNumber(obj2)->getReal();
		
		float matrix[6];
		MatrixUtils::toMatrix(toArray(obj1), matrix);
		SkMatrix mat = MatrixUtils::toMatrix(matrix);
		mat.preScale(x, y);
		
		MatrixUtils::toArray(mat, matrix);
		state.getOpStack().push(MatrixUtils::toArray(matrix));
	} else {
		float x = toNumber(obj2)->getReal();
		float y = toNumber(obj1)->getReal();	
		
		state.getGraphicState()->scale(x, y);
	}
}

void DoOpCoordinateMatrix::ds_rotate::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

void DoOpCoordinateMatrix::ds_concat::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	float mat[6];
	MatrixUtils::toMatrix(toArray(obj1), mat);
	SkMatrix mat1 = MatrixUtils::toMatrix(mat);
	state.getGraphicState()->concat(mat1);
}

void DoOpCoordinateMatrix::ds_concatmatrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;

	float matrix1[6];
	MatrixUtils::toMatrix(toArray(obj3), matrix1);
	float matrix2[6];
	MatrixUtils::toMatrix(toArray(obj2), matrix2);
	float matrix3[6];
	MatrixUtils::toMatrix(toArray(obj1), matrix3);
		
	state.getGraphicState()->concatmatrix(matrix2, matrix1, matrix3);
	state.getOpStack().push(MatrixUtils::toArray(matrix3));
}

void DoOpCoordinateMatrix::ds_transform::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;

	SkPoint p;
	float matrix[6];
	if (obj1->type() == eArray) {
		obj3 = state.getOpStack().pop();
		
		MatrixUtils::toMatrix(toArray(obj1), matrix);
		p.set(toNumber(obj3)->getReal(), toNumber(obj2)->getReal());
	} else {
		MatrixUtils::toArray(state.getGraphicState()->getCtm(), matrix);
		p.set(toNumber(obj2)->getReal(), toNumber(obj1)->getReal());
	}
	p = state.getGraphicState()->transform(matrix, p);
	
	state.getOpStack().push(CRefPtr< _DoObject >(new DoNumber(p.x())));
	state.getOpStack().push(CRefPtr< _DoObject >(new DoNumber(p.y())));
}

void DoOpCoordinateMatrix::ds_dtransform::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;

	SkPoint p;
	float matrix[6];
	if (obj1->type() == eArray) {
		obj3 = state.getOpStack().pop();
		
		MatrixUtils::toMatrix(toArray(obj1), matrix);
		p.set(toNumber(obj3)->getReal(), toNumber(obj2)->getReal());
	} else {
		MatrixUtils::toArray(state.getGraphicState()->getCtm(), matrix);
		p.set(toNumber(obj2)->getReal(), toNumber(obj1)->getReal());
	}
	p = state.getGraphicState()->dtransform(matrix, p);
	
			
	state.getOpStack().push(newNumber(p.x()));
	state.getOpStack().push(newNumber(p.y()));
}

void DoOpCoordinateMatrix::ds_itransform::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

void DoOpCoordinateMatrix::ds_idtransform::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	SkPoint p;
	float matrix[6];
	if (obj1->type() == eArray) {
		obj3 = state.getOpStack().pop();
		
		MatrixUtils::toMatrix(toArray(obj1), matrix);
		p.set(toNumber(obj3)->getReal(), toNumber(obj2)->getReal());
	} else {
		MatrixUtils::toArray(state.getGraphicState()->getCtm(), matrix);
		p.set(toNumber(obj2)->getReal(), toNumber(obj1)->getReal());
	}
	state.getGraphicState()->idtransform(matrix, p);
	
	state.getOpStack().push(newNumber(p.x()));
	state.getOpStack().push(newNumber(p.y()));
}

void DoOpCoordinateMatrix::ds_invertmatrix::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	CXXTHROW
}

